<template>
  <view class="tui-cascade-selection">
    <scroll-view :class="{ 'tui-btm-none': !headerLine }" :scroll-into-view="scrollViewId"
                 :style="{ backgroundColor: headerBgColor }"
                 class="tui-bottom-line" scroll-with-animation
                 scroll-x>
      <view :style="{ height: tabsHeight, backgroundColor: backgroundColor }" class="tui-selection-header">
        <view v-for="(item, idx) in selectedArr" :id="`id_${idx}`"
              :key="idx"
              :class="{ 'tui-font-bold': idx === currentTab && bold }" :data-current="idx"
              :style="{ color: idx === currentTab ? getActiveColor : color, fontSize: size + 'rpx' }"
              class="tui-header-item"
              @tap.stop="swichNav">
          {{ item.text }}
          <view v-if="idx === currentTab && showLine" :style="{ backgroundColor: getLineColor }"
                class="tui-active-line"></view>
        </view>
      </view>
    </scroll-view>
    <swiper :current="defTab" :style="{ height: height, backgroundColor: backgroundColor }" class="tui-selection-list"
            duration="300"
            @change="switchTab">
      <swiper-item v-for="(item, index) in selectedArr" :key="index">
        <scroll-view :scroll-into-view="item.scrollViewId" :style="{ height: height }" class="tui-selection-item"
                     scroll-y>
          <view :style="{ height: firstItemTop }" class="tui-first-item"></view>
          <view v-for="(subItem, subIndex) in item.list" :id="`id_${subIndex}`"
                :key="subIndex" :style="{ padding: padding, backgroundColor: backgroundColor }"
                class="tui-selection-cell"
                @tap.stop="change(index, subIndex, subItem)">
            <icon v-if="item.index === subIndex" :color="getCkMarkColor" :size="checkMarkSize"
                  class="tui-icon-success" type="success_no_circle"></icon>
            <image v-if="subItem.src" :src="subItem.src"
                   :style="{ width: imgWidth, height: imgHeight, borderRadius: radius }"
                   class="tui-cell-img"></image>
            <view :class="{ 'tui-font-bold': item.index === subIndex && textBold, 'tui-flex-shrink': nowrap }"
                  :style="{ color: item.index === subIndex ? textActiveColor : textColor, fontSize: textSize + 'rpx' }"
                  class="tui-cell-title">
              {{ subItem.text }}
            </view>
            <view v-if="subItem.subText" :style="{ color: subTextColor, fontSize: subTextSize + 'rpx' }"
                  class="tui-cell-sub_title">{{ subItem.subText }}
            </view>
          </view>
        </scroll-view>
      </swiper-item>
    </swiper>
  </view>
</template>

<script>
export default {
  name: 'tuiCascadeSelection',
  emits: ['change', 'complete'],
  props: {
    /**
     * 如果下一级是请求返回，则为第一级数据，否则所有数据
     * 数据格式
     [{
     src: "",
     text: "",
     subText: "",
     value: 0,
     children:[{
     text: "",
     subText: "",
     value: 0,
     children:[]
     }]
     }]
     * */
    itemList: {
      type: Array,
      default: () => {
        return [];
      }
    },
    /*
       初始化默认选中数据
       [{
      text: "",//选中text
      subText: '',//选中subText
      value: '',//选中value
      src: '', //选中src，没有则传空或不传
      index: 0, //选中数据在当前layer索引
      list: [{src: "", text: "", subText: "", value: 101}] //当前layer下所有数据集合
      }];

       */
    defaultItemList: {
      type: Array,
      default() {
        return []
      }
    },
    defaultKey: {
      type: String,
      default: 'text'
    },
    //是否显示header底部细线
    headerLine: {
      type: Boolean,
      default: true
    },
    //header背景颜色
    headerBgColor: {
      type: String,
      default: '#FFFFFF'
    },
    //顶部标签栏高度
    tabsHeight: {
      type: String,
      default: '88rpx'
    },
    //默认显示文字
    text: {
      type: String,
      default: '请选择'
    },
    //tabs 文字大小
    size: {
      type: Number,
      default: 28
    },
    //tabs 文字颜色
    color: {
      type: String,
      default: '#555'
    },
    //选中颜色
    activeColor: {
      type: String,
      default: ''
    },
    //选中后文字加粗
    bold: {
      type: Boolean,
      default: true
    },
    //选中后是否显示底部线条
    showLine: {
      type: Boolean,
      default: true
    },
    //线条颜色
    lineColor: {
      type: String,
      default: ''
    },
    //icon 大小
    checkMarkSize: {
      type: Number,
      default: 15
    },
    //icon 颜色
    checkMarkColor: {
      type: String,
      default: ''
    },
    //item 图片宽度
    imgWidth: {
      type: String,
      default: '40rpx'
    },
    //item 图片高度
    imgHeight: {
      type: String,
      default: '40rpx'
    },
    //图片圆角
    radius: {
      type: String,
      default: '50%'
    },
    //item text颜色
    textColor: {
      type: String,
      default: '#333'
    },
    textActiveColor: {
      type: String,
      default: '#333'
    },
    //选中后字体是否加粗
    textBold: {
      type: Boolean,
      default: true
    },
    //item text字体大小
    textSize: {
      type: Number,
      default: 28
    },
    //text 是否不换行
    nowrap: {
      type: Boolean,
      default: false
    },
    //item subText颜色
    subTextColor: {
      type: String,
      default: '#999'
    },
    //item subText字体大小
    subTextSize: {
      type: Number,
      default: 24
    },
    // item padding
    padding: {
      type: String,
      default: '20rpx 30rpx'
    },
    //占位高度，第一条数据距离顶部距离
    firstItemTop: {
      type: String,
      default: '20rpx'
    },
    //swiper 高度
    height: {
      type: String,
      default: '300px'
    },
    //item  swiper 内容部分背景颜色
    backgroundColor: {
      type: String,
      default: '#FFFFFF'
    },
    //子集数据是否请求返回（默认false，一次性返回所有数据）
    request: {
      type: Boolean,
      default: false
    },
    //子级数据（当有改变时，默认当前选中项新增子级数据，request=true时生效）
    receiveData: {
      type: Array,
      default: () => {
        return [];
      }
    },
    //改变值则重置数据
    reset: {
      type: [Number, String],
      default: 0
    }
  },
  computed: {
    getActiveColor() {
      return this.activeColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc';
    },
    getLineColor() {
      return this.lineColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc';
    },
    getCkMarkColor() {
      return this.checkMarkColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc';
    }
  },
  watch: {
    itemList(val) {
      this.initData(val, -1);
    },
    receiveData(val) {
      this.subLevelData(val, this.currentTab);
    },
    reset() {
      this.initData(this.itemList, -1);
    },
    defaultItemList(val) {
      this.setDefaultData(val)
    }
  },
  created() {
    this.setDefaultData(this.defaultItemList)
  },
  data() {
    return {
      currentTab: 0,
      defTab: 0,
      //tab栏scrollview滚动的位置
      scrollViewId: 'id__1',
      selectedArr: []
    };
  },
  methods: {
    setDefaultData(val) {
      let defaultItemList = JSON.parse(JSON.stringify(val || []));
      if (defaultItemList.length > 0) {
        if ((typeof defaultItemList[0] === 'string' || typeof defaultItemList[0] === 'number') && !this
            .request) {
          let subi = -1
          let selectedArr = []
          for (let j = 0, len = defaultItemList.length; j < len; j++) {
            let item = defaultItemList[j]
            let list = []
            let obj = {}
            if (j === 0) {
              list = this.getItemList(-1)
            } else {
              list = this.getItemList(j - 1, subi, selectedArr)
            }
            subi = this.getDefaultIndex(list, item)
            if (subi !== -1) {
              obj = list[subi]
              selectedArr.push({
                text: obj.text || this.text,
                value: obj.value || '',
                src: obj.src || '',
                subText: obj.subText || '',
                index: subi,
                scrollViewId: `id_${subi}`,
                list: list
              })
            }

            if (subi === -1) break;
          }
          this.selectedArr = selectedArr;
          this.defTab = this.currentTab;
          this.$nextTick(() => {
            setTimeout(() => {
              this.currentTab = selectedArr.length - 1;
              this.defTab = this.currentTab;
              this.checkCor();
            }, 20)
          });
        } else {
          defaultItemList.map(item => {
            item.scrollViewId = `id_${item.index}`;
          });
          this.selectedArr = defaultItemList;
          this.defTab = this.currentTab;
          this.$nextTick(() => {
            setTimeout(() => {
              this.currentTab = defaultItemList.length - 1;
              this.defTab = this.currentTab;
              this.checkCor();
            }, 20)
          });
        }

      } else {
        this.initData(this.itemList, -1);
      }
    },
    getDefaultIndex(arr, val) {
      if (!arr || arr.length === 0 || val === undefined) return -1;
      let index = -1;
      let key = this.defaultKey || 'text'
      for (let i = 0, len = arr.length; i < len; i++) {
        if (arr[i][key] == val) {
          index = i;
          break;
        }
      }
      return index;
    },
    initData(data, layer) {
      if (!data || data.length === 0) return;
      if (this.request) {
        //第一级数据
        this.subLevelData(data, layer);
      } else {
        let selectedValue = this.selectedValue || {};
        if (selectedValue.type) {
          this.setDefaultData(selectedValue);
        } else {
          this.subLevelData(this.getItemList(layer, -1), layer);
        }
      }
    },
    removeChildren(data) {
      let list = data.map(item => {
        delete item['children'];
        return item;
      });
      return list;
    },
    getItemList(layer, index, selectedArr) {
      let list = [];
      let arr = JSON.parse(JSON.stringify(this.itemList));
      selectedArr = selectedArr || this.selectedArr
      if (layer == -1) {
        list = this.removeChildren(arr);
      } else {
        let value = selectedArr[0].index;
        value = value === undefined || value == -1 ? index : value;
        if (arr[value] && arr[value].children) {
          list = arr[value].children;
        }
        if (layer > 0) {
          for (let i = 1; i < layer + 1; i++) {
            let val = layer === i ? index : selectedArr[i].index;
            list = val === -1 ? [] : (list[val].children || []);
            if (list.length === 0) break;
          }
        }
        list = this.removeChildren(list);
      }
      return list;
    },
    //滚动切换
    switchTab: function (e) {
      this.currentTab = e.detail.current;
      this.checkCor();
    },
    //点击标题切换当
    swichNav: function (e) {
      let cur = e.currentTarget.dataset.current;
      if (this.currentTab != cur) {
        this.defTab = this.currentTab;
        setTimeout(() => {
          this.currentTab = cur;
          this.defTab = this.currentTab;
        }, 20)
      }
    },
    checkCor: function () {
      let item = this.selectedArr[this.currentTab];
      item.scrollViewId = 'id__1';
      this.$nextTick(() => {
        setTimeout(() => {
          let val = item.index < 2 ? 0 : Number(item.index - 2);
          item.scrollViewId = `id_${val}`;
        }, 20);
      });

      if (this.currentTab > 1) {
        this.scrollViewId = `id_${this.currentTab - 1}`;
      } else {
        this.scrollViewId = `id_0`;
      }
    },
    change(index, subIndex, subItem) {
      let item = this.selectedArr[index];
      if (item.index == subIndex) return;
      item.index = subIndex;
      item.text = subItem.text;
      item.value = subItem.value;
      item.subText = subItem.subText || '';
      item.src = subItem.src || '';
      this.$emit('change', {
        layer: index,
        subIndex: subIndex, //layer=> Array index
        ...subItem
      });

      if (!this.request) {
        let data = this.getItemList(index, subIndex);
        this.subLevelData(data, index);
      }
    },
    //新增子级数据时处理
    subLevelData(data, layer) {
      if (!data || data.length === 0) {
        if (layer == -1) return;
        //完成选择
        let arr = this.selectedArr;
        if (layer < arr.length - 1) {
          let newArr = arr.slice(0, layer + 1);
          this.selectedArr = newArr;
        }
        let result = JSON.parse(JSON.stringify(this.selectedArr));
        let lastItem = result[result.length - 1] || {};
        let text = '';
        result.map(item => {
          text += item.text;
          delete item['list'];
          //delete item['index'];
          delete item['scrollViewId'];
          return item;
        });
        this.$emit('complete', {
          result: result,
          value: lastItem.value,
          text: text,
          subText: lastItem.subText,
          src: lastItem.src
        });
      } else {
        //重置数据（ >layer层级）
        let item = [{
          text: this.text,
          subText: '',
          value: '',
          src: '',
          index: -1,
          scrollViewId: 'id__1',
          list: data
        }];
        if (layer == -1) {
          this.selectedArr = item;
        } else {
          let retainArr = this.selectedArr.slice(0, layer + 1) || [];
          this.selectedArr = retainArr.concat(item);
        }

        let current = this.selectedArr.length - 1;
        if (current >= this.currentTab) {
          this.defTab = this.currentTab
        }
        this.$nextTick(() => {
          setTimeout(() => {
            this.defTab = current;
            this.currentTab = current;
            this.scrollViewId = `id_${this.currentTab > 1 ? this.currentTab - 1 : 0}`;
          }, 50)

        });
      }
    }
  }
};
</script>

<style scoped>
.tui-cascade-selection {
  width: 100%;
  box-sizing: border-box;
}

.tui-selection-header {
  width: 100%;
  display: flex;
  align-items: center;
  position: relative;
  box-sizing: border-box;
}

.tui-bottom-line {
  position: relative;
}

.tui-bottom-line::after {
  width: 100%;
  content: '';
  position: absolute;
  border-bottom: 1rpx solid #eaeef1;
  -webkit-transform: scaleY(0.5) translateZ(0);
  transform: scaleY(0.5) translateZ(0);
  transform-origin: 0 100%;
  bottom: 0;
  right: 0;
  left: 0;
}

.tui-btm-none::after {
  border-bottom: 0 !important;
}

.tui-header-item {
  max-width: 240rpx;
  padding: 15rpx 30rpx;
  box-sizing: border-box;
  flex-shrink: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  position: relative;
}

.tui-font-bold {
  font-weight: bold;
}

.tui-active-line {
  width: 60rpx;
  height: 6rpx;
  border-radius: 4rpx;
  position: absolute;
  bottom: 0;
  right: 0;
  left: 50%;
  transform: translateX(-50%);
}

.tui-selection-cell {
  width: 100%;
  box-sizing: border-box;
  display: flex;
  align-items: center;
}

.tui-icon-success {
  margin-right: 12rpx;
}

.tui-cell-img {
  margin-right: 12rpx;
  flex-shrink: 0;
}

.tui-cell-title {
  word-break: break-all;
}

.tui-flex-shrink {
  flex-shrink: 0;
}

.tui-font-bold {
  font-weight: bold;
}

.tui-cell-sub_title {
  margin-left: 20rpx;
  word-break: break-all;
}

.tui-first-item {
  width: 100%;
}
</style>
